package com.example.test.service;

import com.example.test.DAO.TestLocationMapper;
import com.example.test.DTO.LocationCondition;
import com.example.test.DTO.LocationResult;
import com.example.test.entity.LocationOnly;
import com.example.test.entity.TestLocation;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import software.amazon.awssdk.services.location.model.SearchForTextResult;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class Updater {

    private SqlSessionFactory sqlSessionFactory;

    private GetLocation getLocation;

    public Updater() {
        Properties AWSproperties = new Properties();
        try (InputStream input =
                     new FileInputStream(
                             "src/main/resources/aws/aws-config.properties"
                     )
        ) {
            AWSproperties.load(input);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        getLocation = new GetLocation(
                AWSproperties.getProperty("PlaceIndex"),
                AWSproperties.getProperty("APIkey")
        );

        try (InputStream inputStream =
                     Resources.getResourceAsStream("mybatis/mybatis-config.xml")
        ) {
            sqlSessionFactory =
                    new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<String>
    getLocationTextMM(List<LocationOnly> los) {
        List<String> res = new ArrayList<>();
        for (LocationOnly lo : los) {
            res.add(String.join(", ", lo.getAddress_detail(),
                    lo.getRegion_name_mm(), lo.getCity_name_mm()));
        }
        return res;
    }

    public List<String>
    getLocationTextEN(List<LocationOnly> los) {
        List<String> res = new ArrayList<>();
        for (LocationOnly lo : los) {
            res.add(String.join(", ", lo.getAddress_detail(),
                    lo.getRegion_name_en(), lo.getCity_name_en()));
        }
        return res;
    }

    public List<String>
    getLocationTextCN(List<LocationOnly> los) {
        List<String> res = new ArrayList<>();
        for (LocationOnly lo : los) {
            res.add(String.join(", ", lo.getAddress_detail(),
                    lo.getRegion_name_cn(), lo.getCity_name_cn()));
        }
        return res;
    }

    private List<LocationCondition>
    getLocationCondition(List<LocationOnly> los, LocationOnlyToText lo2t) {
        List<String> texts = lo2t.locationOnlyToText(los);
        List<LocationCondition> res = new ArrayList<>();
        for (String text : texts) {
            LocationCondition tmp = new LocationCondition();
            tmp.setText(text);
            res.add(tmp);
        }
        return res;
    }
//    private List<LocationCondition>
//    getLocationCondition(List<LocationOnly> los) {
//        List<LocationCondition> res = new ArrayList<>();
//        for (LocationOnly lo : los) {
//            LocationCondition tmp = new LocationCondition();
//            tmp.setText(String.join(", ", lo.getAddress_detail(),
//                    lo.getRegion_name_mm(), lo.getCity_name_mm()));
//
//            res.add(tmp);
//        }
//        return res;
//    }

    private List<LocationOnly> getBatch(Integer minId, Integer maxId) {
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            TestLocationMapper testLocationMapper
                    = sqlSession.getMapper(TestLocationMapper.class);
            return testLocationMapper.findLocationOnlyPartially(minId, maxId);
        }
    }

    private void
    extendBatch(Integer minId, Integer maxId, List<LocationResult> lrs) {
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            TestLocationMapper testLocationMapper
                    = sqlSession.getMapper(TestLocationMapper.class);
            for (Integer i = minId; i <= maxId; i++) {
                try {
//                    testLocationMapper.extendGrabLocation(lrs.get(i - minId), i);
//                    testLocationMapper.extendHereLocation(lrs.get(i - minId), i);
                    testLocationMapper.extendEsriLocation(lrs.get(i - minId), i);
                    sqlSession.commit();
                } catch (Exception e) {
                    e.printStackTrace();
                    sqlSession.rollback();
                }
            }
        }
    }

    public void funcTest(Integer minId, Integer maxId, LocationOnlyToText lo2t) {
        List<LocationOnly> los = getBatch(minId, maxId);
        System.out.println("getBatch range:[" + minId + "," + maxId + "]");

        List<LocationCondition> lcs =
                getLocationCondition(los, lo2t);
        System.out.println("getCondition range:[" + minId + "," + maxId + "]");

        List<List<SearchForTextResult>> resultsList =
                getLocation.getPlacesResults(lcs);
        System.out.println("getResult range:[" + minId + "," + maxId + "]");

        List<LocationResult> lrs = new ArrayList<>();
        for (List<SearchForTextResult> results : resultsList) {
            LocationResult lr = new LocationResult();
            if (!results.isEmpty()) {
                SearchForTextResult result = results.get(0);
                List<Double> point = result.place().geometry().point();
                lr.setTotal(result.toString());
                lr.setLongitude(point.get(0));
                lr.setLatitude(point.get(1));

            }
            lrs.add(lr);
        }
        System.out.println("dealResult range:[" + minId + "," + maxId + "]");

        System.out.println("startWriting range:[" + minId + "," + maxId + "]");
        extendBatch(minId, maxId, lrs);
        System.out.println("done range:[" + minId + "," + maxId + "]");

    }

    public List<TestLocation> tmp() {
        List<TestLocation> res = new ArrayList<>();
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            TestLocationMapper testLocationMapper
                    = sqlSession.getMapper(TestLocationMapper.class);
            res = testLocationMapper.testMybatis();
        }
        return res;
    }


}
